package com.ecarx.vhaltests.hy11.testcases.climate;

import android.car.VehicleAreaSeat;
import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VhalUnitTestBase;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;


@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class HvacTemperatureCurrentTest extends VhalUnitTestBase {

    private static final String TAG = "HvacTemperatureCurrentTest";
    private static float halValueRow1Left;
    private static float halValueRow1Right;
    private static float halValueRow2Left;
    private static float halValueRow2Right;
    private static float halValueLeft;
    private static float halValueRight;

    private static int halArea;

    private static final int HVAC_TEMPERATURE_CURRENT = VehiclePropertyIds.HVAC_TEMPERATURE_CURRENT;
    private static final int HVAC_TEMPERATURE_SET = VehiclePropertyIds.HVAC_TEMPERATURE_SET;

    private static final int SERVICE_ID_CLIMATE = 112;
    private static final int OP_ID_CLIMATE = 0xc8;
    private static final int LOCK_TIME = 100;

    private static final int AREA_LEFT = VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER;
    private static final int AREA_RIGHT = VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT;


    final static Object lockRow1Left = new Object();
    final static Object lockRow1Right = new Object();
    final static Object lockRow2Left = new Object();
    final static Object lockRow2Right = new Object();
    final static Object lockLeft = new Object();
    final static Object lockRight = new Object();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, HVAC_TEMPERATURE_CURRENT, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig(OP_ID_CLIMATE);
        delay();
    }

    @Test
    public void testHvacTemperatureCurrentAvailable_01() {
        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_1_LEFT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_LEFT, false);
        delay();

        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_1_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_RIGHT, false);
        delay();

        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_2_LEFT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_2_LEFT, false);
        delay();

        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_2_RIGHT, false);
        delay();

        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER, false);
        delay();

        setHvacTemperatureCurrentAvail(3, 20, VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT, false);
        delay();
    }

    @Test
    public void testHvacTemperatureCurrentAvailable_02() {
        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_1_LEFT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_LEFT, true);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_1_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_RIGHT, true);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_2_LEFT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_2_LEFT, true);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_2_RIGHT, true);
        delay();

        setHvacTemperatureCurrentAvail(1, 19, VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER, true);
        delay();

        setHvacTemperatureCurrentAvail(1, 19, VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentAvailable(VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT, true);
        delay();
    }


    @Test
    public void testHvacTemperatureCurrentGet_01() {
        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_1_LEFT);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_1_LEFT, 25);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_1_RIGHT);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_1_RIGHT, 25);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_2_LEFT);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_2_LEFT, 25);
        delay();

        setHvacTemperatureCurrentAvail(1, 20, VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_2_RIGHT, 25);
        delay();

        setHvacTemperatureCurrentAvail(1, 19, VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER, 25);
        delay();

        setHvacTemperatureCurrentAvail(1, 19, VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT);
        testHvacTemperatureCurrentGet(VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT, 25);
        delay();
    }


    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            try {
                halArea = carPropertyValue.getAreaId();
                Log.d(TAG, "HVAC_TEMPERATURE_CURRENT onChangeEvent value: propertyId ：" + carPropertyValue.getPropertyId()
                        + " propertyValue：" + carPropertyValue.getValue() + " status: " + carPropertyValue.getStatus()
                        + " area：" + carPropertyValue.getAreaId());
                if (halArea == VehicleAreaSeat.SEAT_ROW_1_LEFT) {
                    halValueRow1Left = (float) carPropertyValue.getValue();
                    synchronized (lockRow1Left) {
                        lockRow1Left.notify();
                    }
                } else if (halArea == VehicleAreaSeat.SEAT_ROW_1_RIGHT) {
                    halValueRow1Right = (float) carPropertyValue.getValue();
                    synchronized (lockRow1Right) {
                        lockRow1Right.notify();
                    }
                } else if (halArea == VehicleAreaSeat.SEAT_ROW_2_LEFT) {
                    halValueRow2Left = (float) carPropertyValue.getValue();
                    synchronized (lockRow2Left) {
                        lockRow2Left.notify();
                    }
                } else if (halArea == VehicleAreaSeat.SEAT_ROW_2_RIGHT) {
                    halValueRow2Right = (float) carPropertyValue.getValue();
                    synchronized (lockRow2Right) {
                        lockRow2Right.notify();
                    }
                } else if (halArea == (VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER)) {
                    halValueLeft = (float) carPropertyValue.getValue();
                    synchronized (lockLeft) {
                        lockLeft.notify();
                    }
                } else if (halArea == (VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT)) {
                    halValueRight = (float) carPropertyValue.getValue();
                    synchronized (lockRight) {
                        lockRight.notify();
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };


    public void lockWait(int area) {
        try {
            if (area == VehicleAreaSeat.SEAT_ROW_1_LEFT) {
                synchronized (lockRow1Left) {
                    lockRow1Left.wait(LOCK_TIME);
                }
            } else if (area == VehicleAreaSeat.SEAT_ROW_1_RIGHT) {
                synchronized (lockRow1Right) {
                    lockRow1Right.wait(LOCK_TIME);
                }
            } else if (area == VehicleAreaSeat.SEAT_ROW_2_LEFT) {
                synchronized (lockRow2Left) {
                    lockRow2Left.wait(LOCK_TIME);
                }
            } else if (area == VehicleAreaSeat.SEAT_ROW_2_RIGHT) {
                synchronized (lockRow2Right) {
                    lockRow2Right.wait(LOCK_TIME);
                }
            } else if (area == (VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER)) {
                synchronized (lockLeft) {
                    lockLeft.wait(LOCK_TIME);
                }
            } else if (area == (VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT)) {
                synchronized (lockRight) {
                    lockRight.wait(LOCK_TIME);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public void testHvacTemperatureCurrentAvailable(int area, boolean avail) {
        boolean isAvail = mCarPropertyMgr.isPropertyAvailable(HVAC_TEMPERATURE_CURRENT, area);
        Log.d(TAG, "testHvacTemperatureCurrentAvailable isAvail：" + isAvail);
        Assert.assertEquals(avail,isAvail);

    }

    public void testHvacTemperatureCurrentGet(int area, float value) {
        Log.d(TAG, "testHvacTemperatureCurrentGet area：" + area + " value: " + value);
        mCarPropertyMgr.setFloatProperty(HVAC_TEMPERATURE_SET, area, value);
        lockWait(area);
        float hvacTemperature = mCarPropertyMgr.getFloatProperty(HVAC_TEMPERATURE_CURRENT, area);
        Assert.assertEquals(value, hvacTemperature, 0);
    }

    public void setHvacTemperatureCurrentAvail(int avail, int value, int area) {
        Log.d(TAG, "setHvacTemperatureSetAvail area:" + area + " avail：" + avail);
        IpcpClient ipcpClient = new IpcpClient();
        String availabilityIndex = "";
        String dataIndex = "";
        if (area == VehicleAreaSeat.SEAT_ROW_1_LEFT) {
            availabilityIndex = "pacllefttemp.availability";
            dataIndex = "pacllefttemp.data";
        } else if (area == VehicleAreaSeat.SEAT_ROW_1_RIGHT) {
            availabilityIndex = "paclrighttemp.availability";
            dataIndex = "paclrighttemp.data";
        } else if (area == VehicleAreaSeat.SEAT_ROW_2_LEFT) {
            availabilityIndex = "paclseclefttemp.availability";
            dataIndex = "paclseclefttemp.data";
        } else if (area == VehicleAreaSeat.SEAT_ROW_2_RIGHT) {
            availabilityIndex = "paclsecrighttemp.availability";
            dataIndex = "paclsecrighttemp.data";
        } else if (area == (VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER)) {
            availabilityIndex = "pacllefttemp.availability";
            dataIndex = "pacllefttemp.data";
        } else if (area == (VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT)) {
            availabilityIndex = "paclrighttemp.availability";
            dataIndex = "paclrighttemp.data";
        }
        String[] config_indexs = {availabilityIndex, dataIndex};
        int[] values = {avail, value};
        boolean bb = ipcpClient.setClimaSignal(SERVICE_ID_CLIMATE, OP_ID_CLIMATE, config_indexs, values);
        Assert.assertTrue(bb);
        lockWait(area);
    }


    private static void setConfig(int OperId) {
        IpcpClient ipcpClient = new IpcpClient();
        int climateOperId[] = {OperId};
        ipcpClient.setConfig(SERVICE_ID_CLIMATE, climateOperId);
    }

}
